#include <stdio.h>
#include "stdafx.h"
#include "Solver.h"
#include "Settings.h"

Solver :: Solver(Configurator* configurator)
{
	dwarfConfigurator = configurator;					// process settings from the command line 
	dwarfConfigurator -> WriteSettings();
	dwarfConfigurator -> GetContent(&mainContent, &contentSize);
}

void Solver::Solve()
{
	Map();						// Collect the word entries into the StringEntries list
	Reduce();					// Count the number of entry of each word into the StringTotal map
}

string Solver::TransformCharFragment(int begin, int end)
{
	int length = end - begin;
	char* currentWord = (char*) malloc (sizeof(char)*length);				// dynamic memory allocation for new char array
	for (int j = 0; j < length; j++)
	{
		currentWord[j] = mainContent[begin + j];								// filling the array
	}
	string transform(reinterpret_cast<const char*>(currentWord), length);	// convert to string
	free(currentWord);														// free memory from char array
	return transform;
}

// Traverses the string 'content'. Collect each word as substring of 'content'. Change the 'stringEntries' value
void Solver::Map()
{
	int i = 0;										// iteration counter
    int count = 0;						// local variable for storing the length of each word
	while (i < contentSize)
	{
		if ((mainContent[i] > 47 && mainContent[i] < 58)  ||
            (mainContent[i] > 96 && mainContent[i] < 123) ||
            (mainContent[i] > 64 && mainContent[i] < 91)  ||
             mainContent[i] == 95						  ||
             mainContent[i] == 45					      ||
             mainContent[i] == 39)
		{
			count++;														// getting the length of a string
        }
        else
        {
			if (count > 0)
			{
				string stringFragment = TransformCharFragment(i - count, i);
				stringEntries.push_back(stringFragment);					// add substring
            }
			string stringFragment = TransformCharFragment(i, i + 1);
			stringEntries.push_back(stringFragment);						// add single-char string
            count = 0;														// start length counting of a new word
        }
        i++;
    }
	free(mainContent);		// clearing the unused memory (all data is already consisted in stringEntries)
} 

//Groups 'stringEntries' elements and count the number of entry of each word
void Solver::Reduce()
{
	stringEntries.sort();
    int count = 1;										// local variable for storing the count of each word
	string strCur;
	string strPre = stringEntries.front();
	stringEntries.pop_front();	
	while (!stringEntries.empty())						// traverse the list	
    {
		strCur = stringEntries.front();
		stringEntries.pop_front();										
		if (strCur == strPre)							// checking the equivalence of adjoining words
		{
			count++;                                    // getting count of the word
        }
		else
        {
			stringTotal[strPre] = count;				// add to the final list
            count = 1;									// start the next word's count
        }
		strPre = strCur;
    }
	stringTotal[strPre] = count;				// add to the final list
	stringEntries.clear();			// clearing the unused memory (all entrines is already consisted in stringTotal)
}

void Solver::Finish(double time)	// Problem results output
{
	dwarfConfigurator -> Close(time, stringTotal);
	stringTotal.clear();			// clearing the unused memory (all data is already printed)
}